const contentType = {
    get: undefined,
    post: 'application/x-www-form-urlencoded; charset=UTF-8',
    postJson: 'application/json; charset=UTF-8',
    file: 'multipart/form-data'
};
import {layer} from '../layer';

class AjaxModel {

    constructor() {
        this.header = {};//	该对象下的所有数据均会添加到Ajax请求头中。主要用于发送token
        this.loadingNum = 0;    //正在进行中的启用了加载动画的Ajax请求数量
        this._lock = false;
    }


    /**
     * 创建请求头
     * @param type
     * @returns {{"X-Requested-With": string, "Content-Type": *}}
     */
    newHeader(type = 'get') {
        let data = {
            'X-Requested-With': 'XMLHttpRequest',
            'Content-Type': contentType[type],
        };
        if (type === 'get') {
            data = {
                token: this.header.token
            };
        }
        Object.assign(data, this.header);
        return data;
    }

    /**
     * 防止重复提交
     * @returns {Promise<void>}
     */
    whileUnlock() {
        if (this._lock) {
            return Promise.reject();
        } else {
            this._lock = true;
            return Promise.resolve();
        }
    }

    /**
     * 解除锁定
     */
    unlock() {
        this._lock = false;
    }

    /**
     * 服务端出错时触发
     * @returns {Promise<never>}
     */
    onServerError() {
        return Promise.reject('服务器未响应，或接口地址有误');
    }

    /**
     * 出错时触发
     * @param msg
     */
    onError(msg) {
        layer.error(msg);
    }

    /**
     * 请求开始前触发
     */
    loadingStart() {
        this.loadingNum++;
        this.onLoadingShow();
    }

    /**
     * 请求结束时触发
     */
    loadingStop() {
        this.loadingNum--;
        if (this.loadingNum === 0) {
            this.onLoadingHide();
        }
    }

    /**
     * 需要显示加载动画时触发
     */
    onLoadingShow() {
        layer.loading();
    }

    /**
     * 需要停止加载动画时触发
     */
    onLoadingHide() {
        layer.hideLoading();
    }

    /**
     * 请求结束后触发
     * @param result
     * @returns {Promise<any>}
     */
    afterRequest(result) {
        const res = this.filter(result);
        return new Promise((resolve, reject) => {
            if (res.success || res.code === 0 || res.code === 200) {
                resolve(res);
            } else {
                this.onError(res.msg);
                reject(res.msg);
            }
        });
    }

    /**
     * 请求结束后触发 用于对数据进行统一的预处理
     * @param result
     * @returns {*}
     */
    filter(result) {
        return result[1].data;
    }

    /**
     * 请求开始前触发 用于为所有请求添加统一的数据
     * @param data
     * @returns {*}
     */
    everyPara(data) {
        return data;
    }

    /**
     * get方式提交数据
     * @param url
     * @param paras
     * @param showLoading
     * @param useFilter
     */
    get(url, data, showLoading = true, useFilter = true) {
        if (typeof url !== 'string' || url.length === 0) {
            throw 'Ajax请求地址不能为空'
        }
        this.everyPara(data);
        if (showLoading) {
            this.loadingStart();
        }
        return uni.request({
            method: 'GET',
            url,
            data: data,
            timeout: 30000,
            header: this.newHeader()
        }).catch(() => {
            if (showLoading) {
                this.loadingStop();
            }
            return this.onServerError();
        }).then(result => {
            if (showLoading) {
                this.loadingStop();
            }
            if (useFilter) {
                return this.afterRequest(result);
            } else {
                return Promise.resolve(result.data);
            }
        });
    }

    /**
     * post form方式提交数据
     * @param url
     * @param paras
     * @param showLoading
     * @param useFilter
     */
    post(url, data, showLoading = true, useFilter = true) {
        if (typeof url !== 'string' || url.length === 0) {
            throw 'Ajax请求地址不能为空'
        }


        this.everyPara(data);
        if (showLoading) {
            this.loadingStart();
        }

        return uni.request({
            method: 'POST',
            url,
            data: data,
            timeout: 30000,
            header: this.newHeader('post')
        }).catch(() => {
            if (showLoading) {
                this.loadingStop();
            }
            return this.onServerError();
        }).then(result => {
            if (showLoading) {
                this.loadingStop();
            }
            if (useFilter) {
                return this.afterRequest(result);
            } else {
                return Promise.resolve(result.data);
            }
        });

    }

    /**
     * post方式提交json数据
     * @param url
     * @param paras
     * @param showLoading
     * @param useFilter
     */
    postJson(url, data, showLoading = true, useFilter = true) {
        if (typeof url !== 'string' || url.length === 0) {
            throw 'Ajax请求地址不能为空'
        }
        this.everyPara(data);
        if (showLoading) {
            this.loadingStart();
        }
        return uni.request({
            method: 'POST',
            url,
            data,
            timeout: 30000,
            header: this.newHeader('postJson')
        }).catch(() => {
            if (showLoading) {
                this.loadingStop();
            }
            return this.onServerError();
        }).then(result => {
            if (showLoading) {
                this.loadingStop();
            }
            if (useFilter) {
                return this.afterRequest(result);
            } else {
                return Promise.resolve(result.data);
            }
        });

    }

    /**
     * get方式获取文本数据
     * @param url
     * @param paras
     * @param showLoading
     */
    getText(url, paras, showLoading = true) {
        this.everyPara(paras);
        return this.get(url, paras, showLoading, false);
    }

    /**
     * 获取分页数据 默认为get方式
     * @param url
     * @param page
     * @param opt
     * @param mode
     * @returns {PromiseLike<T | never> | Promise<T | never>}
     */
    getPage(url, page = 1, opt, mode = 'get') {
        opt = Object.assign({
            paras: {},
            limit: 20,
            onEnd: function (isEmpty) {
            },
            filter: function (result) {
                return result;
            }
        }, opt || {});
        const paras = Object.assign(this.buildPagePara(page, opt.limit), opt.paras);

        return this[mode](url, paras).then(function (result) {
            if (!result) {
                opt.onEnd(page === 1);
                return {
                    total: 0,
                    data: []
                }
            }
            result = opt.filter(result);
            result.total = parseInt(result.total);//后台给出的可能是字符串
            result.data = result.data || [];
            if (result.data.length < opt.limit) {
                opt.onEnd(page === 1);
            }
            return result;
        });
    }

    /**
     * 构造分页参数
     * @param page
     * @param limit
     * @returns {{offset: number, limit: *}}
     */
    buildPagePara(page, limit) {
        return {
            limit,
            offset: (page - 1) * limit
        }
    }
}


export {
    AjaxModel
}
